0
1
00:00:00,550 --> 00:00:01,110
All right.
1

2
00:00:01,110 --> 00:00:04,940
So in this lesson we're gonna do a couple of things.
2

3
00:00:05,130 --> 00:00:12,210
We're gonna be plotting our gradient descent path on our 3D surface so we can see our algorithm slowly
3

4
00:00:12,210 --> 00:00:15,420
working its way down to the bottom of the bowl.
4

5
00:00:15,540 --> 00:00:23,310
But this is also a really good opportunity to learn a little bit more about numpy's n-dimensional
5

6
00:00:23,400 --> 00:00:30,000
arrays because these things are incredibly powerful and we're gonna be taking a look at how we can append
6

7
00:00:30,000 --> 00:00:36,330
values to arrays, how we can concatenate arrays, how we can slice arrays and how we can select particular
7

8
00:00:36,330 --> 00:00:43,680
columns of an array. Let's commemorate the upcoming topics with a new section heading.
8

9
00:00:44,690 --> 00:00:51,620
So I'm going to change this cell to Markdown and then I'm going to put two pound symbols here and then I'll
9

10
00:00:51,620 --> 00:01:07,240
write "Graphing 3D Gradient Descent & Advanced Numpy Arrays". And I'll hit Shift+Enter.
10

11
00:01:07,240 --> 00:01:12,710
I'm also going to add a few more cells to the bottom so that way I'm working more in the center of the
11

12
00:01:12,710 --> 00:01:19,640
screen. Now to do our plotting what we're going to do is we're gonna scroll a little bit up and we're
12

13
00:01:19,640 --> 00:01:28,290
going to copy this cell here, I'm going to copy the cell and I'm going to paste this cell here.
13

14
00:01:28,740 --> 00:01:32,100
And the reason I'm doing this is so that I can add some code to it.
14

15
00:01:32,250 --> 00:01:38,310
I want to modify the cells so we have a record of what we've been doing but this is also the cell which
15

16
00:01:38,370 --> 00:01:42,880
is gonna contain the code that tracks the progress of our gradient descent.
16

17
00:01:42,900 --> 00:01:49,840
So I'm going to add some code to this. Now, as before the values that we're gonna be tracking are how
17

18
00:01:49,840 --> 00:01:56,550
are our parameters change as the loop runs and the place where I'm going to store all these values that we're
18

19
00:01:56,550 --> 00:02:04,650
gonna be tracking is going to be a variable that I'm going to call values_array and
19

20
00:02:04,650 --> 00:02:11,090
the very first value this values array is going to have is going to consist of our initial guess, our
20

21
00:02:11,670 --> 00:02:13,510
params.
21

22
00:02:13,650 --> 00:02:15,450
So leaving the code like this,
22

23
00:02:15,540 --> 00:02:20,490
let's take a really quick look at the shape of our values array.
23

24
00:02:20,760 --> 00:02:29,730
So I'm going to print the "values_array.shape" and see what I get.
24

25
00:02:29,850 --> 00:02:35,340
The result is gonna be the very first line that's printed below the cell so I can see that this is a
25

26
00:02:35,340 --> 00:02:42,870
tuple and my array just consists of two elements and that's no surprise, those elements are gonna be
26

27
00:02:42,990 --> 00:02:46,630
1.8 and 1.0.
27

28
00:02:46,920 --> 00:02:53,190
And that's all this shape attribute is showing us. Now the thing is, I can transform this array if I want
28

29
00:02:53,190 --> 00:03:02,100
to. Instead of having a one dimensional array with two elements, I can have a two dimensional array with
29

30
00:03:02,130 --> 00:03:05,350
one element each instead.
30

31
00:03:05,490 --> 00:03:08,380
But why would I want two dimensions?
31

32
00:03:08,400 --> 00:03:16,230
Well what I want to do is I want to keep all the x values in one dimension and then I want to keep all
32

33
00:03:16,230 --> 00:03:20,520
the y values in the second dimension.
33

34
00:03:20,520 --> 00:03:28,290
So what I'm going to do is I want to transform my array into a new shape so handily there is something
34

35
00:03:28,290 --> 00:03:33,240
called a reshape method which takes two inputs -
35

36
00:03:33,240 --> 00:03:39,080
one is the number of rows and the other is the number of columns.
36

37
00:03:39,090 --> 00:03:44,250
So rows are first so it's gonna be 1,2 -
37

38
00:03:44,460 --> 00:03:48,190
those are gonna be the arguments to the reshape method.
38

39
00:03:48,190 --> 00:03:55,530
Now if I rerun the cell have a look at the output below the cell to see how many rows and how many columns
39

40
00:03:55,830 --> 00:03:57,460
my array has now.
40

41
00:03:58,380 --> 00:04:06,570
So you should see this updated to 1,2 - one row, two columns. I now have a two dimensional array.
41

42
00:04:07,110 --> 00:04:13,560
My x value is gonna be in my first dimension and my y value is going to be in my second dimension.
42

43
00:04:14,700 --> 00:04:15,270
Okay yeah,
43

44
00:04:15,300 --> 00:04:20,740
so you might say "Yeah Phillip great preamble, but where are you going with this?".
44

45
00:04:20,740 --> 00:04:27,750
And what I would say to that is I'm setting the scene for the code I'm going to add to my for loop right
45

46
00:04:27,750 --> 00:04:28,040
here.
46

47
00:04:28,710 --> 00:04:36,540
But before I do that and move on to the code inside the gradient descent, let me add a new cell below
47

48
00:04:36,540 --> 00:04:44,680
this one and just go through a few methods and a few techniques for working with multi-dimensional arrays.
48

49
00:04:44,790 --> 00:04:54,940
So I'm going to add a little comment here and I'm going to call this "Advanced Numpy Array Practice".
49

50
00:04:55,650 --> 00:05:00,000
And the first thing I'm going to do of course is create a dummy array.
50

51
00:05:00,000 --> 00:05:01,190
This array is going to have a name,
51

52
00:05:01,220 --> 00:05:08,850
it's going to be called kirk, and it's going to be equal to np.array, so we're creating an array, parentheses,
52

53
00:05:08,850 --> 00:05:13,440
and then I want this array to have one row and two columns.
53

54
00:05:13,440 --> 00:05:21,510
So I'm going to have one square bracket and then a second square bracket and inside I'm going to put
54

55
00:05:21,600 --> 00:05:22,230
a string.
55

56
00:05:22,230 --> 00:05:32,020
I'm going to say "Captain" and then comma and then I'm going to have another string and that's gonna read "Guitar".
56

57
00:05:32,130 --> 00:05:37,230
So two strings surrounded by two square brackets.
57

58
00:05:37,230 --> 00:05:41,140
So just to verify that we indeed have a two dimensional array,
58

59
00:05:41,280 --> 00:05:51,180
let's print out "kirk.shape" below the cell and hit Shift+Enter. There we see that indeed we have
59

60
00:05:51,240 --> 00:05:56,830
one row and two columns by using this notation here.
60

61
00:05:56,880 --> 00:05:57,380
All right.
61

62
00:05:57,390 --> 00:06:04,230
So upwards and onwards. This time we're gonna create a two by two array.
62

63
00:06:04,230 --> 00:06:07,640
So this is gonna be two rows, two columns.
63

64
00:06:07,830 --> 00:06:18,640
And I'm going to call this array "hs_band" and we've said it's equal to "np.array()",
64

65
00:06:19,140 --> 00:06:24,060
and then I'm going to add two square brackets again and inside the second square bracket I'm going to
65

66
00:06:24,060 --> 00:06:29,760
add a string and call it "Black Thought".
66

67
00:06:29,880 --> 00:06:36,740
And then after the string and I'm going to add a comma and then another string "MC" and then after that first
67

68
00:06:36,750 --> 00:06:44,040
closing square bracket I'm going to add another comma and then I'm going to open another square bracket,
68

69
00:06:44,040 --> 00:06:53,600
and add the string "Questlove", comma and then the string "Drums" and then you'll have two square brackets at
69

70
00:06:53,600 --> 00:06:56,250
the end and the parentheses.
70

71
00:06:56,300 --> 00:07:07,420
So this is our second array and let's print out the shape. So "print(hs_band.shape)" and
71

72
00:07:07,470 --> 00:07:14,110
here we can see that indeed this array is two by two - two rows two columns.
72

73
00:07:14,130 --> 00:07:20,530
Now when working with multi-dimensional arrays like this let me ask you a question.
73

74
00:07:20,880 --> 00:07:30,020
How do you think we would go about selecting a particular item in the array? So previously we just used
74

75
00:07:30,110 --> 00:07:34,870
the square bracket notation and then we supplied an index.
75

76
00:07:34,880 --> 00:07:38,270
Let's see what happens when we do that on a two dimensional array.
76

77
00:07:38,300 --> 00:07:46,040
So I'll print and I'll just put down in the string the code I'm going to add after the string.
77

78
00:07:46,050 --> 00:07:52,230
So I'm going to say "hs_band[0]",
78

79
00:07:52,510 --> 00:08:00,540
and then after the string I'm going to add a comma and then put the actual Python code here "hs_band[0]".
79

80
00:08:00,780 --> 00:08:09,300
I'm going to hit Shift+Enter here. So we can see here that if I use the very, very same approach with a two dimensional
80

81
00:08:09,300 --> 00:08:15,840
array for selecting a particular item as with a one dimensional array I don't get back one item,
81

82
00:08:15,960 --> 00:08:26,160
instead I'm getting back an entire row. I'm getting back all the elements in that first row. But the thing
82

83
00:08:26,160 --> 00:08:27,810
is that kind of makes sense, right?
83

84
00:08:27,810 --> 00:08:31,760
We have two dimensions so we shouldn't be supplying one index,
84

85
00:08:31,800 --> 00:08:35,680
we should be supplying two indices.
85

86
00:08:35,760 --> 00:08:36,900
How do we do that?
86

87
00:08:36,930 --> 00:08:38,820
Let me just copy this line of Python code here.
87

88
00:08:40,790 --> 00:08:42,220
And add a print statement.
88

89
00:08:42,230 --> 00:08:44,060
Paste the print statement below.
89

90
00:08:44,510 --> 00:08:51,010
And then instead of having just "hs_band[0]",
90

91
00:08:51,230 --> 00:08:57,540
I'm going to add another pair of square brackets here and between those I'm going to put the value 1.
91

92
00:08:58,780 --> 00:09:06,140
I'm going to add that to my string as well so that we're consistent and I'm going to hit Shift+Enter and what
92

93
00:09:06,140 --> 00:09:14,150
you should see is that in this case we're selecting one particular element, we're selecting the first
93

94
00:09:14,150 --> 00:09:18,500
row and then the first column in that row.
94

95
00:09:18,500 --> 00:09:25,790
So we're honing in on the string "MC". If you have trouble seeing this in your print statements then
95

96
00:09:26,150 --> 00:09:33,620
you can put a few spaces here and a semicolon, might make it a little easier and then you'll have a nice
96

97
00:09:33,620 --> 00:09:41,000
separation between the the string and the value that you're getting back with your Python code.
97

98
00:09:41,010 --> 00:09:41,290
All right.
98

99
00:09:41,290 --> 00:09:46,460
So this was a really one difference between working with a one dimensional array and a two dimensional
99

100
00:09:46,460 --> 00:09:47,110
array.
100

101
00:09:47,420 --> 00:09:48,500
Now, as a challenge,
101

102
00:09:48,500 --> 00:09:55,460
can you modify this print statement to select the word "Questlove" and have that printed out right here
102

103
00:09:55,460 --> 00:09:57,740
where it says "MC" currently?
103

104
00:09:57,740 --> 00:10:04,490
I'll give you a few seconds to pause the video and give this a shot. So I hope you had a chance to solve
104

105
00:10:04,490 --> 00:10:05,580
this.
105

106
00:10:05,590 --> 00:10:08,060
Questlove is in the second row.
106

107
00:10:08,060 --> 00:10:09,260
So we start counting at zero.
107

108
00:10:09,260 --> 00:10:16,120
Second row is at index 1 and it is the first item in the second row,
108

109
00:10:16,130 --> 00:10:17,240
so first column.
109

110
00:10:17,240 --> 00:10:20,680
So this would be column zero.
110

111
00:10:20,720 --> 00:10:24,510
Let me Shift+Enter to prove to you that this is indeed the case.
111

112
00:10:24,620 --> 00:10:25,260
And there we go.
112

113
00:10:25,310 --> 00:10:28,370
We see Questlove printed out below.
113

114
00:10:28,370 --> 00:10:32,010
Now let's create another array but through a different way.
114

115
00:10:32,060 --> 00:10:33,800
I'm going to call this array
115

116
00:10:33,800 --> 00:10:42,750
"the_roots". I'm going to set it equal to "np.append",
116

117
00:10:42,920 --> 00:10:46,930
so I'm not going to write "np.array", I'm going to write "np.append".
117

118
00:10:47,120 --> 00:10:53,690
I'm gonna open the parentheses and inside these parentheses I'm going to supply three arguments, three inputs -
118

119
00:10:54,170 --> 00:11:02,360
the first argument is gonna be the array I want to append items to, this is gonna be "arr = hs_
119

120
00:11:02,480 --> 00:11:10,180
band", I'm going to put comma and supply my second argument and these are gonna be the values so I'm going to write
120

121
00:11:10,640 --> 00:11:19,030
"values = kirk" and then I'm going to supply the third argument and this is going to be the axis. Axis is gonna
121

122
00:11:19,040 --> 00:11:28,420
be equal to zero. And below all this I'm going add a print statements, so I'm going to say "print(the_roots)".
122

123
00:11:28,580 --> 00:11:33,710
Now before I hit Shift+Enter, I'm going to make sure my variable names are the same.
123

124
00:11:33,710 --> 00:11:34,250
So,
124

125
00:11:34,340 --> 00:11:44,570
so this is gonna be "the_roots = np.append(arr=hs_band, values=
125

126
00:11:44,600 --> 00:11:52,550
kirk, axis=0)" and then I am indeed printing this variable here, printing the_roots.
126

127
00:11:52,570 --> 00:11:59,390
Now let me Shift+Enter so you can see what this looks like. Now what we've got is that below the cell, there
127

128
00:11:59,390 --> 00:12:02,480
are six elements being printed out.
128

129
00:12:02,560 --> 00:12:11,170
We've got the four elements from hs_band and we've appended two extra elements, namely "Captain" and "Guitar"
129

130
00:12:11,590 --> 00:12:13,330
to these four elements.
130

131
00:12:13,450 --> 00:12:18,220
So our array called the_roots is actually three by two,
131

132
00:12:18,220 --> 00:12:20,370
it's a three by two array.
132

133
00:12:20,440 --> 00:12:25,000
Now let's take a look at this append method. The append method takes three arguments - 
133

134
00:12:25,000 --> 00:12:30,510
the first one is, well, the element where the items are going to be appended to
134

135
00:12:30,800 --> 00:12:38,310
and the second argument here is our array which was appended to hs_band and then we've got
135

136
00:12:38,320 --> 00:12:39,590
this third argument here -
136

137
00:12:39,630 --> 00:12:47,940
axis; axis=0 and the first time I saw this I thought "Man, this is a really confusing word" but
137

138
00:12:47,960 --> 00:12:56,490
it's actually pretty simple. Axis basically means should we add our values as a row
138

139
00:12:56,810 --> 00:13:00,360
or should we add them as a column.
139

140
00:13:00,390 --> 00:13:03,270
So what we've done is we said "axis=0",
140

141
00:13:03,510 --> 00:13:10,980
and that means that our values inside kirk are added as a row on to our two by two array. So our two by
141

142
00:13:10,980 --> 00:13:14,680
two array became a three by two array.
142

143
00:13:14,880 --> 00:13:23,170
If axis instead was equal to one, then we would be trying to add our new values as a column.
143

144
00:13:23,170 --> 00:13:30,270
But you have to be careful with these axes. If you try to change this to one and press Shift+Enter it
144

145
00:13:30,320 --> 00:13:36,960
actually won't work, because Kirk is actually a one by two array and not a two by one array.
145

146
00:13:37,140 --> 00:13:44,220
So you have to be careful because your axes have to match you can't add up or append items to arrays
146

147
00:13:44,550 --> 00:13:47,700
where the dimensions don't match.
147

148
00:13:47,700 --> 00:13:56,780
Kirk has one row, two columns and you can't add a one row two columns as columns to a two by two.
148

149
00:13:57,030 --> 00:14:04,690
If you actually wanted to do that you'd have to reshape the Kirk array to be two by one.
149

150
00:14:04,710 --> 00:14:06,530
This is the only way it would work.
150

151
00:14:06,750 --> 00:14:14,790
In this case you would indeed get a two by three matrix, a two by three array.
151

152
00:14:14,970 --> 00:14:22,620
So I hope this makes sense - if you're appending stuff to an existing array then the shapes of the array
152

153
00:14:22,650 --> 00:14:25,310
have to be compatible.
153

154
00:14:25,380 --> 00:14:30,280
So in this case what I actually want to do is I want to add rows on to my existing array so I'm going to say 
154

155
00:14:30,300 --> 00:14:31,990
axis=0
155

156
00:14:32,100 --> 00:14:35,390
and the way I've made these arrays the rows already match.
156

157
00:14:35,490 --> 00:14:36,810
So I'm going to hit Shift+Enter again.
157

158
00:14:36,890 --> 00:14:39,500
So you refresh this and you can see, indeed,
158

159
00:14:39,520 --> 00:14:45,090
okay I've got an artist and I've got a role in the band and here's another artist and here's another
159

160
00:14:45,090 --> 00:14:45,960
role in the band,
160

161
00:14:46,590 --> 00:14:54,010
and so on. Now I'm not gonna make you add all the band members of the roots individually that would be
161

162
00:14:54,460 --> 00:15:02,260
very, very time consuming but um let's just pretend this band has three members for now.
162

163
00:15:02,260 --> 00:15:09,960
And suppose that we want to select all the band members just by their nicknames.
163

164
00:15:09,970 --> 00:15:16,680
So we want to just take an entire column from this array.
164

165
00:15:16,730 --> 00:15:18,390
How would we do that?
165

166
00:15:18,440 --> 00:15:26,180
And the answer is that this is actually really, really, really easy to do with some special Python notation
166

167
00:15:26,330 --> 00:15:29,170
for slicing arrays.
167

168
00:15:29,180 --> 00:15:29,950
Let me show you.
168

169
00:15:30,080 --> 00:15:40,990
If I print out, uh, add a string here "Printing nicknames...", comma and here's how we slice our
169

170
00:15:40,990 --> 00:15:41,700
array.
170

171
00:15:41,710 --> 00:15:44,680
Here's how we only print out the first column.
171

172
00:15:45,090 --> 00:15:52,470
We're gonna say "the_roots[]", and I'm going to supply two values -
172

173
00:15:52,470 --> 00:16:02,460
the first one is gonna be a column and I'm going to have a comma and then we're to have a zero.
173

174
00:16:02,730 --> 00:16:09,030
So what we're saying here is  - take all the rows, so a colon is the shorthand notation here for selecting
174

175
00:16:09,210 --> 00:16:10,260
all the rows,
175

176
00:16:10,260 --> 00:16:17,670
all the values in the rows and that second argument here, that zero refers to the first column.
176

177
00:16:17,730 --> 00:16:20,870
Let me hit Shift+Enter to show you what I mean.
177

178
00:16:21,090 --> 00:16:28,620
I'm going to scroll down and there you should see "Printing nicknames... ['Blackthorn',  'Questlove', 'Captain']".
178

179
00:16:29,740 --> 00:16:30,310
All right.
179

180
00:16:30,310 --> 00:16:33,640
So let's practice this one more time.
180

181
00:16:33,640 --> 00:16:40,070
I'm going to add another band member though, so I'm going to say the_roots and I'm going
181

182
00:16:40,090 --> 00:16:50,080
to update our roots array with "np.append" and for the array I'm going to choose the_roots
182

183
00:16:51,010 --> 00:16:54,550
and for the values I'm gonna say
183

184
00:16:54,820 --> 00:16:58,470
"values  = [[]]", 
184

185
00:16:58,540 --> 00:17:04,180
So I'm going to add the values here directly and then between those square brackets I'm going to provide
185

186
00:17:04,540 --> 00:17:05,590
two strings -
186

187
00:17:05,590 --> 00:17:08,320
the first one is gonna say "Malik
187

188
00:17:08,560 --> 00:17:23,400
B", and then comma, single quotes MC, closing square brackets comma, axis again is equal to zero.
188

189
00:17:23,460 --> 00:17:30,930
Having added another band member here let's print out the roles. I'm going to say "Printing
189

190
00:17:31,050 --> 00:17:35,180
band roles..."
190

191
00:17:35,590 --> 00:17:39,100
and then after the string, put a comma,
191

192
00:17:39,330 --> 00:17:42,580
and now I'm going to throw the ball over into your court.
192

193
00:17:42,650 --> 00:17:48,440
I'm going to challenge you to print out all the band roles in the roots.
193

194
00:17:48,440 --> 00:17:53,370
So I'm going to give you a few seconds to pause the video and write the Python code that will print
194

195
00:17:53,370 --> 00:17:58,600
out all the band members roles below the cell.
195

196
00:17:58,850 --> 00:18:00,830
And here's the solution.
196

197
00:18:01,400 --> 00:18:08,990
Again we're gonna use our array slicing notation so I'm going to say "the_roots[
197

198
00:18:09,140 --> 00:18:13,870
:,1]", I'm going to hit Shift+Enter.
198

199
00:18:13,910 --> 00:18:21,280
I can see now that we've got two MCs, one set of drums and one guitar. All right,
199

200
00:18:21,310 --> 00:18:28,590
so with these array techniques covered we're ready to move on to graphing our gradient descent. And
200

201
00:18:29,020 --> 00:18:35,340
if you haven't heard of the roots then check out our song of theirs called "The Next Movement".
201

202
00:18:35,350 --> 00:18:38,220
That's one of my personal favorites. A long time ago,
202

203
00:18:38,230 --> 00:18:39,880
I actually went to see these guys live.
203

204
00:18:39,910 --> 00:18:46,660
They came down to London and I think one of the things that impressed me most was that during the performance
204

205
00:18:47,260 --> 00:18:49,520
the band members traded the instruments,
205

206
00:18:49,690 --> 00:18:55,030
so like the drummer took the guitar and the guitarist took the vocals and the vocalist took the bass
206

207
00:18:55,120 --> 00:18:56,020
and so on.
207

208
00:18:56,350 --> 00:19:02,020
And having done that they proceeded to play their next song just showing everyone in the audience that
208

209
00:19:02,020 --> 00:19:07,710
they weren't one trick ponies but actual musicians who could do more than than one thing.
209

210
00:19:07,720 --> 00:19:11,250
I mean I haven't gone to that many concerts but I've never seen that before.
210

211
00:19:11,290 --> 00:19:12,510
So yeah check out these guys.
211

212
00:19:12,520 --> 00:19:13,060
They're pretty cool.
